﻿using GuangHaoJie.FMS.Domain;
using GuangHaoJie.FMS.IRepository;
using Microsoft.Extensions.Logging;
using Simple.Tools;
using Simple.Tools.SnowFlake;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace GuangHaoJie.FMS.Repository
{
	public class BaseRepository<TEntity,TKey>: IBaseRepository<TEntity,TKey> where TEntity : Domain.BaseEntity<TKey>,new()
	{
		[Autowired]
		protected ISqlSugarClient _client { get; set; }

		/// <summary>
		/// 
		/// </summary>
		/// 
		[Autowired]
		protected ILogger<BaseRepository<TEntity, TKey>> logger { get; set; }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="client"></param>
		public BaseRepository()
		{

		}

		/// <summary>
		/// 添加 并且返回实体
		/// </summary>
		/// <param name="entity"></param>
		/// <returns></returns>
		public virtual async Task<TEntity> CreateReturnEntityAsync(TEntity entity)
		{

			SetId(entity);
			return await _client.Insertable(entity).ExecuteReturnEntityAsync();
		}
		/// <summary>
		/// 添加 
		/// </summary>
		/// <param name="entity"></param>
		/// <returns></returns>
		public virtual async Task<int> CreateReturnIdentityAsync(TEntity entity)
		{
			SetId(entity);
			return await _client.Insertable(entity).ExecuteReturnIdentityAsync();
		}
		/// <summary>
		/// 创建数据
		/// </summary>
		/// <param name="entity"></param>
		/// <returns></returns>
		public virtual async Task<bool> CreateAsync(TEntity entity)
		{
			SetId(entity);
			return await _client.Insertable(entity).ExecuteCommandAsync() > 0;
		}
		/// <summary>
		/// 创建集合
		/// </summary>
		/// <param name="entitys"></param>
		/// <returns></returns>
		public virtual async Task<bool> CreateAsync(List<TEntity> entitys)
		{
			foreach (var entity in entitys)
			{
				SetId(entity);
			}
			return await _client.Insertable(entitys).ExecuteCommandAsync() == entitys.Count;
		}

		/// <summary>
		/// 更新实体
		/// </summary>
		/// <param name="entity"></param>
		/// <returns></returns>
		public virtual async Task<bool> UpdateAsync(TEntity entity)
		{
			return await _client.Updateable(entity).ExecuteCommandAsync() > 0;
		}
		/// <summary>
		/// 更新集合
		/// </summary>
		/// <param name="entitys"></param>
		/// <returns></returns>
		public virtual async Task<bool> UpdateAsync(List<TEntity> entitys)
		{
			return await _client.Updateable(entitys).ExecuteCommandAsync() == entitys.Count;
		}
		/// <summary>
		/// 删除实体
		/// </summary>
		/// <param name="lamada"></param>
		/// <returns></returns>
		public virtual async Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> lamada)
		{
			return await _client.Deleteable(lamada).ExecuteCommandAsync() > 0;
		}
		/// <summary>
		/// 软删除
		/// </summary>
		/// <param name="lamada"></param>
		/// <returns></returns>
		public virtual async Task<bool> SoftDeleteAsync(Expression<Func<TEntity, bool>> lamada)
		{
			return await _client.Updateable(lamada).ExecuteCommandAsync() > 0;
		}

		/// <summary>
		/// 软删除
		/// </summary>
		/// <param name="lamada"></param>
		/// <returns></returns>
		public virtual async Task<bool> SoftDeleteAsync(TEntity entity)
		{
			return await _client.Updateable(entity).ExecuteCommandAsync() > 0;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="expression"></param>
		/// <returns></returns>
		public ISugarQueryable<TEntity> Where(Expression<Func<TEntity, bool>> expression)
		{
			return _client.Queryable<TEntity>().Where(expression);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="expression"></param>
		/// <returns></returns>
		public async Task<int> CountAsync(Expression<Func<TEntity, bool>> expression)
		{
			return await _client.Queryable<TEntity>().Where(expression).CountAsync();
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="lamada"></param>
		/// <returns></returns>
		public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> lamada)
		{
			return await _client.Queryable<TEntity>().AnyAsync(lamada);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="lamada"></param>
		/// <returns></returns>
		public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> lamada)
		{
			return await _client.Queryable<TEntity>().FirstAsync(lamada);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="lamada"></param>
		/// <param name="currentPage"></param>
		/// <param name="pageSize"></param>
		/// <returns></returns>
		public async Task<IEnumerable<TEntity>> SelectAsync(Expression<Func<TEntity, bool>> lamada, int currentPage = 0, int pageSize = 20)
		{
			return await _client.Queryable<TEntity>().Where(lamada).ToPageListAsync(currentPage, pageSize);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="lamada"></param>
		/// <param name="currentPage"></param>
		/// <param name="pageSize"></param>
		/// <returns></returns>
		public IEnumerable<TEntity> Select(Expression<Func<TEntity, bool>> lamada, int currentPage = 0, int pageSize = 20)
		{
			return _client.Queryable<TEntity>().Where(lamada).ToPageList(currentPage, pageSize);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="lamada"></param>
		/// <returns></returns>
		public Task<TEntity> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> lamada)
		{
			return _client.Queryable<TEntity>().Where(lamada).SingleAsync(lamada);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public async Task<int> SaveQueuesAsync()
		{
			return await _client.SaveQueuesAsync();
		}
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public int SaveChanges()
		{
			return _client.SaveQueues();
		}
		public void SetId(TEntity entity)
		{
			if (entity.Id is long longId)
			{
				if (longId <= 0)
				{
					longId = Worker.GetId();
					if (longId is TKey tkey)
					{
						entity.Id = tkey;
					}
				}
			}

			if (entity.Id is string strId)
			{
				if (entity.Id == null || string.IsNullOrEmpty(strId))
				{
					strId = Guid.NewGuid().ToString();
					if (strId is TKey tkey)
					{
						entity.Id = tkey;
					}
				}
			}
		}
		public void EnableLogger()
		{
			//输出sql,查看执行sql
			//5.0.8.2 获取无参数化 SQL 
			//UtilMethods.GetSqlString(DbType.SqlServer,sql,pars)

#if DEBUG
			_client.Aop.OnLogExecuting = (sql, pars) =>
			{
				if (logger != null)
				{
					StringBuilder logInfo=new StringBuilder();
					logInfo.Append($"====================");
					logInfo.Append($"Date:{DateTime.Now}\t \t sql:{sql}");
					logInfo.Append($"====================");
					if (!SimpleCheck.IsNotNullOrEmpty(pars))
					{
						foreach (var item in pars)
						{
							string value = item.Value == null ? "null" : item.Value.ToString();
							logInfo.Append($"ParameterName:{item.ParameterName}\t \t value:{value} \t\t typeName:{item.TypeName}");
						}
						logInfo.Append($"====================");
					}
					logger.LogInformation(logInfo.ToString());
				}
			};
#endif

		}

		public void BeginTran()
		{
			_client.Ado.BeginTran();
		}

		public async Task BeginTranAsync()
		{
			await _client.Ado.BeginTranAsync();
		}

		public void CommitTran()
		{
			_client.Ado.CommitTran();
		}

		public async Task CommitTranAsync()
		{
			await _client.Ado.CommitTranAsync();
		}

		public void RollbackTran()
		{
			_client.Ado.RollbackTran();
		}

		public async Task RollbackTranAsync()
		{
			await _client.Ado.RollbackTranAsync();
		}


	}
}
